#include "asignar.h"

Asignar::Asignar(Sentencia *next, Variable *variable, Expr *expr, int fila, int col):Sentencia(next,fila,col)
{
    this->expr=expr;
    this->variable=variable;
}

void Asignar::setVariable(Variable *variable)
{
    this->variable=variable;
}

void Asignar::setExpr(Expr *expr)
{
    this->expr=expr;
}

Variable *Asignar::getVariable()
{
    return this->variable;
}

Expr *Asignar::getExpr()
{
    return this->expr;
}

string Asignar::is()
{
    return "ASIGNAR";
}

void Asignar::validarRegistros(Registro *tts_v, Registro *tts_e)
{
    if(tts_v->getTs()->getTable().size()==tts_e->getTs()->getTable().size()){
        for(int i=0;i<(int)tts_v->getTs()->getTable().size();i++){
            if(tts_v->getTs()->getTable().at(i)->getTipo()->is().compare(tts_e->getTs()->getTable().at(i)->getTipo()->is())!=0){
                stringstream out;
                out<<"Los Registros No tienen la misma estructura// Fila:"<<this->getFila()<<endl;
                throw exception(out.str().c_str());
            }else{
                if(tts_v->getTs()->getTable().at(i)->getTipo()->is().compare("REGISTRO")==0){

                    Registro *a = (Registro*)tts_v->getTs()->getTable().at(i)->getTipo();
                    Registro *b = (Registro*)tts_e->getTs()->getTable().at(i)->getTipo();
                    validarRegistros(a,b);

                }else{
                    if(tts_v->getTs()->getTable().at(i)->getTipo()->is().compare("ARREGLO")==0){
                        Arreglo *a = (Arreglo*)tts_v->getTs()->getTable().at(i)->getTipo();
                        Arreglo *b = (Arreglo*)tts_e->getTs()->getTable().at(i)->getTipo();
                        if(a->getTipo()->is().compare(b->getTipo()->is())==0){
                            if(a->getTipo()->is().compare("REGISTRO")==0){
                                Registro *c = (Registro*)a->getTipo();
                                Registro *d = (Registro*)b->getTipo();
                                validarRegistros(c,d);

                            }
                        }else{
                            stringstream out;
                            out<<"Tipos de Datos No son Compatibles// Fila:"<<this->getFila()<<endl;
                            throw exception(out.str().c_str());
                        }

                    }

                }
            }
        }



    }else{
        stringstream out;
        out<<"Los Registros No tienen la misma estructura"<< "// Fila:"<<this->getFila()<<endl;
        throw exception(out.str().c_str());
    }
}

Tipo_ts *Asignar::validarSemantica(Tabla_Simbolos *tabla_de_tipo, Tabla_Simbolos *tabla_de_varaible)
{
    Tipo_ts *ttsV = this->variable->validarSemantica(tabla_de_tipo,tabla_de_varaible);
    Tipo_ts *ttsE= this->expr->validarSemantica(tabla_de_tipo,tabla_de_varaible);
    if(ttsV->is().compare(ttsE->is())==0){
        if(ttsV->is().compare("REGISTRO")==0){
            Registro *tts_v = (Registro*)ttsV;
            Registro *tts_e = (Registro*)ttsE;
            validarRegistros(tts_v,tts_e);

        }
        if(ttsV->is().compare("ARREGLO")==0){
            Arreglo *a = (Arreglo*)ttsV;
            Arreglo *b = (Arreglo*)ttsV;
            if(a->getTipo()->is().compare(b->getTipo()->is())==0){
                if(a->getTipo()->is().compare("REGISTRO")==0){
                    Registro *c = (Registro*)a->getTipo();
                    Registro *d = (Registro*)b->getTipo();
                    validarRegistros(c,d);

                }
            }else{
                stringstream out;
                out<<"Tipos de Datos No son Compatibles "<< this->getVariable()->getValor()<< "// Fila:"<<this->getFila()<<endl;
                throw exception(out.str().c_str());
            }

        }



    }else{
        if((ttsV->is().compare("ENTERO")==0 || ttsV->is().compare("REAL")==0) && (ttsE->is().compare("ENTERO")==0 || ttsE->is().compare("REAL")==0)){

        }else{
            stringstream out;
            out<<"Tipos de Datos No son Compatibles "<< this->getVariable()->getValor()<< "// Fila:"<<this->getFila()<<endl;
            throw exception(out.str().c_str());
        }

    }
    if(this->getNext()!=0){
        this->getNext()->SetReturn(this->GetReturn());
        this->getNext()->validarSemantica(tabla_de_tipo,tabla_de_varaible);

    }
    return ttsV;
}

string Asignar::generarCodigo(GenerarVariable* var,Tabla_Simbolos *tabla_de_tipo,Tabla_Simbolos *tabla_de_varaible)
{
    string codigo;
    Tipo_ts *ttsV = this->variable->validarSemantica(tabla_de_tipo,tabla_de_varaible);
    if(ttsV->is().compare("CADENA")==0){
        Cadena *cadena = (Cadena*)ttsV;
        codigo = this->expr->generarCodigo(var,tabla_de_tipo,tabla_de_varaible).codigo;
        codigo += "strncpy("+this->variable->generarCodigo(var,tabla_de_tipo,tabla_de_varaible).codigo+",";
        codigo += this->expr->generarCodigo(var,tabla_de_tipo,tabla_de_varaible).lugar;
        QString s;
        s.setNum(cadena->getSize(),10);
        codigo += ","+s.toStdString()+");\n";
        codigo += this->variable->generarCodigo(var,tabla_de_tipo,tabla_de_varaible).codigo+"["+s.toStdString()+"]";
        codigo += "='\\0';\n";

    }else{
        codigo = this->variable->generarCodigo(var,tabla_de_tipo,tabla_de_varaible).codigo +" = "+this->expr->generarCodigo(var,tabla_de_tipo,tabla_de_varaible).codigo+";\n" ;
    }

    if(this->getNext()!=0){
        codigo += this->getNext()->generarCodigo(var,tabla_de_tipo,tabla_de_varaible);
    }

    return codigo;
}
